package com.skt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.skt.config.CacheConstants;
import com.skt.domain.DTO.CostumeQueryDTO;
import com.skt.domain.PO.Costume;
import com.skt.domain.VO.CostumeDetailVO;
import com.skt.domain.VO.CostumeVO;
import com.skt.exception.*;
import com.skt.mapper.CostumeMapper;
import com.skt.result.PageResult;
import com.skt.security.LoginUser;
import com.skt.service.CostumeService;
import com.skt.utils.LogUtil;
import com.skt.utils.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Set;

import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CostumeServiceImpl extends ServiceImpl<CostumeMapper, Costume> implements CostumeService {

    private final RedisUtil redisUtil;
    private final CostumeMapper costumeMapper;




    /**
     * 分页查询服装列表
     * @param queryParams
     * @return
     */
    @Override
    public PageResult<CostumeVO> getCostumeList(CostumeQueryDTO queryParams) {
        LogUtil.info("COSTUME", "GET_LIST", "开始分页查询服装列表，参数: {}", queryParams);

        // 1. 用户身份认证
        getCurrentUserId();

        // 2. 参数验证
        validateGetCostumeListParam(queryParams);

        // 3. 构建查询条件
        LambdaQueryWrapper<Costume> queryWrapper = buildQueryWrapper(queryParams);

        // 4. 执行分页查询
        IPage<Costume> costumePage = executePageQuery(queryParams, queryWrapper);

        // 5. 转换为VO并返回结果
        PageResult<CostumeVO> result = convertToPageResult(costumePage);

        LogUtil.info("COSTUME", "GET_LIST", "分页查询服装列表成功，总记录数: {}", costumePage.getTotal());
        return result;
    }

 
    /**
     * 获取服装详情
     * @param costumeId
     * @return
     */
    @Override
    public CostumeDetailVO getCostumeDetail(Long costumeId) {
        LogUtil.info("COSTUME", "GET_DETAIL", "开始查询服装详情，ID: {}", costumeId);

        // 设置追踪ID和计时
        LogUtil.setTraceId();
        LogUtil.startTimer("COSTUME_DETAIL_QUERY");

        try {
            // 1. 服装ID参数校验
            validateCostumeId(costumeId);

            // 2. 从Redis中查询服装信息
            Costume costume = queryCostumeFromRedis(costumeId);
            if (costume != null) {
                LogUtil.info("COSTUME", "GET_DETAIL", "从缓存获取服装详情成功，ID: {}", costumeId);
                CostumeDetailVO result = convertToDetailVO(costume);
                // 设置动态信息（如是否收藏）
                setDynamicInfo(result);
                LogUtil.stopTimer();
                return result;
            }

            LogUtil.info("COSTUME", "GET_DETAIL", "缓存未命中，从数据库查询服装详情，ID: {}", costumeId);

            // 3. 从数据库中查询服装信息
            costume = queryCostumeFromDatabase(costumeId);

            // 4. 将查询结果写入缓存
            setCostumeToCache(costume);

            // 5. 数据转换
            CostumeDetailVO result = convertToDetailVO(costume);

            // 6. 设置动态信息
            setDynamicInfo(result);

            LogUtil.info("COSTUME", "GET_DETAIL", "获取服装详情成功，ID: {}", costumeId);
            LogUtil.stopTimer();
            return result;

        } catch (BusinessException e) {
            LogUtil.error("COSTUME", "GET_DETAIL", "获取服装详情业务异常，ID: {}", costumeId, e);
            throw e;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "GET_DETAIL", "获取服装详情系统异常，ID: {}", costumeId, e);
            throw CostumeException.of(CostumeErrorCode.QUERY_COSTUME_DETAIL_FAILED, "查询服装详情失败");
        } finally {
            LogUtil.clearContext();
        }
    }

    /**
     * 搜索商品
     * @param queryParams
     * @return
     */
    @Override
    public PageResult<CostumeVO> searchCostumes(CostumeQueryDTO queryParams) {
        LogUtil.info("COSTUME", "SEARCH", "开始搜索商品，参数: {}", queryParams);

        // 1. 参数校验
        validateSearchCostumesParams(queryParams);

        // 2. 查询条件构造
        LambdaQueryWrapper<Costume> queryWrapper = buildSearchWrapper(queryParams);

        // 3. 执行查询
        IPage<Costume> costumePage = executePageSearch(queryParams, queryWrapper);

        // 4. 转换为VO
        PageResult<CostumeVO> result = convertToPageResult(costumePage);

        LogUtil.info("COSTUME", "SEARCH", "搜索商品成功，关键词: {}, 总记录数: {}",
                queryParams.getKeyword(), costumePage.getTotal());
        return result;
    }

    /**
     * 执行搜索分页查询
     * @param queryParams
     * @param queryWrapper
     * @return
     */
    private IPage<Costume> executePageSearch(CostumeQueryDTO queryParams, LambdaQueryWrapper<Costume> queryWrapper) {
        Page<Costume> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());

        try {
            IPage<Costume> result = costumeMapper.selectPage(page, queryWrapper);
            return result;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "PAGE_SEARCH", "分页搜索失败，参数: {}", queryParams, e);
            throw CostumeException.of(CostumeErrorCode.QUERY_COSTUME_LIST_FAILED, "搜索商品失败");
        }
    }

    /**
     * 构建搜索查询条件
     * @param queryParams
     * @return
     */
    private LambdaQueryWrapper<Costume> buildSearchWrapper(CostumeQueryDTO queryParams) {
        LambdaQueryWrapper<Costume> queryWrapper = Wrappers.<Costume>lambdaQuery()
                .eq(Costume::getStatus, (byte) 1);

        // 关键词模糊搜索
        if (StringUtils.isNotBlank(queryParams.getKeyword())) {
            String keyword = queryParams.getKeyword().trim();
            queryWrapper.and(wrapper -> wrapper
                    .like(Costume::getName, keyword)
                    .or()
                    .like(Costume::getBrand, keyword)
                    .or()
                    .like(Costume::getDescription, keyword)
            );
        }

        // 商家筛选
        if (queryParams.getMerchantId() != null) {
            queryWrapper.eq(Costume::getMerchantId, queryParams.getMerchantId());
        }

        // 价格范围查询
        if (queryParams.getMinRentalPrice() != null) {
            queryWrapper.ge(Costume::getRentalPrice, queryParams.getMinRentalPrice());
        }

        if (queryParams.getMaxRentalPrice() != null) {
            queryWrapper.le(Costume::getRentalPrice, queryParams.getMaxRentalPrice());
        }

        // 排序处理
        applySearchSorting(queryWrapper, queryParams);

        return queryWrapper;
    }

    /**
     * 应用搜索排序
     * @param queryWrapper
     * @param queryParams
     */
    private void applySearchSorting(LambdaQueryWrapper<Costume> queryWrapper, CostumeQueryDTO queryParams) {
        String sortBy = queryParams.getSortBy();
        String sortOrder = queryParams.getSortOrder();

        if (StringUtils.isBlank(sortBy)) {
            // 默认按创建时间降序
            queryWrapper.orderByDesc(Costume::getCreatedAt);
            return;
        }

        boolean isAsc = "asc".equalsIgnoreCase(sortOrder);

        switch (sortBy.toLowerCase()) {
            case "price":
                queryWrapper.orderBy(true, isAsc, Costume::getRentalPrice);
                break;
            case "sales":
                // 如果没有sales字段，使用创建时间代替
                queryWrapper.orderBy(true, isAsc, Costume::getCreatedAt);
                break;
            case "createtime":
            default:
                queryWrapper.orderBy(true, isAsc, Costume::getCreatedAt);
                break;
        }
    }

    
    /**
     * 参数校验
     *
     * @param queryParams
     */
    private void validateSearchCostumesParams(CostumeQueryDTO queryParams) {
        if (queryParams.getMinRentalPrice() != null &&
                queryParams.getMaxRentalPrice() != null &&
                queryParams.getMinRentalPrice().compareTo(queryParams.getMaxRentalPrice()) > 0) {
            throw CostumeException.of(CostumeErrorCode.MIN_PRICE_GREATER_THAN_MAX, "最低价格不能大于最高价格");
        }

        if (queryParams.getMerchantId() != null && queryParams.getMerchantId() <= 0) {
            throw CostumeException.of(CostumeErrorCode.MERCHANT_NOT_FOUND, "商户不存在");
        }

        if (StringUtils.isNotBlank(queryParams.getSortBy())) {
            Set<String> validSortFields = Set.of("price", "sales", "createTime");
            if (!validSortFields.contains(queryParams.getSortBy())) {
                queryParams.setSortBy("price");
            }
        }

        if (queryParams.getInStockOnly().equals(true) && queryParams.getStock() <= 0) {
            throw CostumeException.of(CostumeErrorCode.COSTUME_OUT_OF_STOCK, "商品已售罄");
        }

        if (queryParams.getKeyword().length() > 50) {
            throw CostumeException.of(CostumeErrorCode.SEARCH_KEYWORD_TOO_LONG, "搜索关键词过长");
        }
    }

    /**
     * 将服装信息写入缓存
     * @param costume 服装信息
     */
    private void setCostumeToCache(Costume costume) {
        if (costume != null && costume.getId() != null) {
            try {
                String cacheKey = CacheConstants.COSTUME_INFO_KEY_PREFIX + costume.getId();
                redisUtil.set(cacheKey, costume, 2 * 60 * 60, TimeUnit.SECONDS); // 2小时过期
                LogUtil.info("COSTUME", "SET_CACHE", "服装信息已缓存，ID: {}", costume.getId());
            } catch (Exception e) {
                LogUtil.warn("COSTUME", "SET_CACHE", "缓存写入失败，ID: {}，错误: {}", costume.getId(), e.getMessage());
            }
        }
    }

    /**
     * 设置动态信息（如是否收藏）
     * @param detailVO 服装详情VO
     */
    private void setDynamicInfo(CostumeDetailVO detailVO) {
        try {

            // 计算可用库存
            if (detailVO.getStockQuantity() != null && detailVO.getRentedQuantity() != null) {
                detailVO.setAvailableStock(detailVO.getStockQuantity() - detailVO.getRentedQuantity());
            }

        } catch (Exception e) {
            // 如果获取用户信息失败，默认设置为false
            detailVO.setIsFavorited(false);
            LogUtil.warn("COSTUME", "SET_DYNAMIC_INFO", "设置动态信息失败: {}", e.getMessage());
        }
    }

    /**
     * 实体转换为详情VO
     * @param costume 服装实体
     * @return 服装详情VO
     */
    private CostumeDetailVO convertToDetailVO(Costume costume) {
        if (costume == null) {
            return null;
        }

        CostumeDetailVO detailVO = new CostumeDetailVO();
        // 使用BeanUtil复制共同属性
        BeanUtil.copyProperties(costume, detailVO);

        // 设置详情特有字段的默认值或计算值
        if (costume.getStock() != null) {
            detailVO.setStockQuantity(costume.getStock());
            // 已租数量需要从订单表查询，这里先设为0
            detailVO.setRentedQuantity(0);
            detailVO.setAvailableStock(costume.getStock());
        }

        // 设置其他默认值
        detailVO.setSalesCount(0);
        detailVO.setRating(BigDecimal.ZERO);
        detailVO.setReviewCount(0);
        detailVO.setDeposit(BigDecimal.ZERO);
        detailVO.setMinRentalDays(1);
        detailVO.setCleaningFee(BigDecimal.ZERO);

        // 如果是单张图片，转换为列表
        if (StringUtils.isNotBlank(costume.getImageUrl())) {
            detailVO.setImageUrls(List.of(costume.getImageUrl()));
        }

        return detailVO;
    }

    /**
     * 从Redis中查询服装信息（添加防御性检查）
     * @param costumeId
     * @return 服装信息，查询失败返回null
     */
    private Costume queryCostumeFromRedis(Long costumeId) {
        // 防御性检查
        if (redisUtil == null) {
            LogUtil.warn("COSTUME", "REDIS_QUERY", "RedisUtil未初始化，跳过缓存查询");
            return null;
        }

        try {
            String costumeKey = CacheConstants.COSTUME_INFO_KEY_PREFIX + costumeId;
            Object cached = redisUtil.get(costumeKey);

            if (cached instanceof Costume) {
                LogUtil.debug("COSTUME", "REDIS_QUERY", "Redis缓存命中，ID: {}", costumeId);
                return (Costume) cached;
            }

            return null;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "REDIS_QUERY", "Redis查询异常，ID: {}，错误: {}", costumeId, e.getMessage());
            return null; // Redis异常不影响主流程，降级到数据库查询
        }
    }

    /**
     * 从数据库中查询服装信息
     * @param costumeId 服装ID
     * @return 服装实体
     */
    private Costume queryCostumeFromDatabase(Long costumeId) {
        LogUtil.info("COSTUME", "DB_QUERY", "开始从数据库查询服装信息，ID: {}", costumeId);

        try {
            // 使用Lambda查询，只查询需要的字段，提高性能
            LambdaQueryWrapper<Costume> queryWrapper = Wrappers.<Costume>lambdaQuery()
                    .eq(Costume::getId, costumeId)
                    .eq(Costume::getStatus, (byte) 1); // 只查询在售状态的服装

            Costume costume = costumeMapper.selectOne(queryWrapper);

            if (costume == null) {
                LogUtil.warn("COSTUME", "DB_QUERY", "服装信息不存在或已被删除，ID: {}", costumeId);
                throw CostumeException.of(CostumeErrorCode.COSTUME_NOT_FOUND, "服装不存在或已被删除");
            }

            // 检查服装状态（虽然查询条件已经过滤了状态，但这里可以再次验证）
            if (costume.getStatus() != 1) {
                LogUtil.warn("COSTUME", "DB_QUERY", "服装不可用，ID: {}, 状态: {}", costumeId, costume.getStatus());
                throw CostumeException.of(CostumeErrorCode.COSTUME_NOT_AVAILABLE, "服装暂不可用");
            }

            LogUtil.info("COSTUME", "DB_QUERY", "数据库查询服装信息成功，ID: {}, 名称: {}",
                    costumeId, costume.getName());
            return costume;

        } catch (CostumeException e) {
            // 业务异常直接抛出
            throw e;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "DB_QUERY", "数据库查询服装信息异常，ID: {}, 错误: {}",
                    costumeId, e.getMessage(), e);
            throw CostumeException.of(CostumeErrorCode.QUERY_COSTUME_DETAIL_FAILED, "查询服装信息失败");
        }
    }

    /**
     * 验证服装ID参数
     * @param costumeId 服装ID
     */
    private void validateCostumeId(Long costumeId) {
        if (costumeId == null || costumeId <= 0) {
            LogUtil.error("COSTUME", "VALIDATE_ID", "服装ID参数无效: {}", costumeId);
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "服装ID不能为空且必须大于0");
        }

        LogUtil.debug("COSTUME", "VALIDATE_ID", "服装ID验证通过: {}", costumeId);
    }

    /**
     * 构建查询条件包装器
     * @param queryParams 查询参数
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<Costume> buildQueryWrapper(CostumeQueryDTO queryParams) {
        LambdaQueryWrapper<Costume> queryWrapper = Wrappers.<Costume>lambdaQuery()
                .eq(Costume::getStatus, (byte) 1) // 只查询在售状态的服装
                .orderBy(true, "asc".equals(queryParams.getSortOrder()),
                        getSortField(queryParams.getSortBy()));

        // 关键词搜索（支持名称、品牌、描述模糊搜索）
        if (StringUtils.isNotBlank(queryParams.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                    .like(Costume::getName, queryParams.getKeyword())
                    .or()
                    .like(Costume::getBrand, queryParams.getKeyword())
                    .or()
                    .like(Costume::getDescription, queryParams.getKeyword())
            );
        }

        // 商家查询
        if (queryParams.getMerchantId() != null) {
            queryWrapper.eq(Costume::getMerchantId, queryParams.getMerchantId());
        }

        // 价格范围查询
        if (queryParams.getMinRentalPrice() != null) {
            queryWrapper.ge(Costume::getRentalPrice, queryParams.getMinRentalPrice());
        }

        if (queryParams.getMaxRentalPrice() != null) {
            queryWrapper.le(Costume::getRentalPrice, queryParams.getMaxRentalPrice());
        }

        LogUtil.info("COSTUME", "BUILD_QUERY", "构建查询条件完成，关键词: {}, 商家ID: {}, 价格范围: {}-{}",
                queryParams.getKeyword(), queryParams.getMerchantId(), queryParams.getMinRentalPrice(), queryParams.getMaxRentalPrice());

        return queryWrapper;
    }

    /**
     * 获取排序字段
     * @param sortBy 排序字段名称
     * @return 对应的实体类字段
     */
    private com.baomidou.mybatisplus.core.toolkit.support.SFunction<Costume, ?> getSortField(String sortBy) {
        switch (sortBy) {
            case "price":
                return Costume::getRentalPrice;
            case "sales":
                // 注意：Costume实体中没有salesCount字段，使用createdAt代替
                return Costume::getCreatedAt;
            case "createTime":
            default:
                return Costume::getCreatedAt;
        }
    }

    /**
     * 执行分页查询
     * @param queryParams 查询参数
     * @param queryWrapper 查询条件
     * @return 分页结果
     */
    private IPage<Costume> executePageQuery(CostumeQueryDTO queryParams,
                                            LambdaQueryWrapper<Costume> queryWrapper) {
        Page<Costume> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());

        try {
            // page == getBaseMapper().selectPage(page, queryWrapper);
            IPage<Costume> result = page(page, queryWrapper);
            LogUtil.info("COSTUME", "EXECUTE_QUERY", "数据库查询成功，页码: {}, 页大小: {}, 总记录数: {}",
                    queryParams.getPageNum(), queryParams.getPageSize(), result.getTotal());
            return result;
        } catch (Exception e) {
            LogUtil.error("COSTUME", "EXECUTE_QUERY", "分页查询服装列表失败，错误信息: {}", e.getMessage());
            throw CostumeException.of(CostumeErrorCode.QUERY_COSTUME_LIST_FAILED, "查询服装列表失败");
        }
    }

    /**
     * 转换为分页结果VO
     * @param costumePage 实体分页结果
     * @return VO分页结果
     */
    private PageResult<CostumeVO> convertToPageResult(IPage<Costume> costumePage) {
        List<CostumeVO> costumeVOList = costumePage.getRecords().stream()
                // costume -> convertToVO(costume) == this::convertToVO
                .map(this::convertToVO)
                .collect(Collectors.toList());

        // 使用PageResult的构造函数，保持兼容性
        return new PageResult<>(
                costumePage.getCurrent(), // 当前页码（第几页）
                costumePage.getSize(), // 每页大小（每页多少条）
                costumePage.getTotal(), // 总记录数（总共多少条）
                costumeVOList // 当前页的数据列表
        );
    }

    /**
     * 实体转换为VO
     * @param costume 服装实体
     * @return 服装VO
     */
    private CostumeVO convertToVO(Costume costume) {
        if (costume == null) {
            return null;
        }

        CostumeVO vo = new CostumeVO();
        BeanUtil.copyProperties(costume, vo);

        return vo;
    }

    /**
     * 分页查询服装列表接口方法参数验证
     * @param queryParams
     */
    private void validateGetCostumeListParam(CostumeQueryDTO queryParams) {
        LogUtil.info("COSTUME", "VALIDATE_PARAMS", "开始验证查询参数");

        // 基础验证
        basicsValidateParams(queryParams);

        // 业务验证
        businessValidateParams(queryParams);

        LogUtil.info("COSTUME", "VALIDATE_PARAMS", "参数验证完成");
    }

    /**
     * 业务验证
     * @param queryParams
     */
    private void businessValidateParams(CostumeQueryDTO queryParams) {
        if (queryParams.getCategoryId() != null && queryParams.getCategoryId() < 0) {
            LogUtil.error("COSTUME", "VALIDATE_BUSINESS", "分类ID不能小于0: {}", queryParams.getCategoryId());
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "分类ID不能小于0");
        }

        if (queryParams.getMerchantId() != null && queryParams.getMerchantId() < 0) {
            LogUtil.error("COSTUME", "VALIDATE_BUSINESS", "商家ID不能小于0: {}", queryParams.getMerchantId());
            throw ValidationException.of(ValidationErrorCode.PARAM_INVALID, "商家ID不能小于0");
        }

        if (queryParams.getMinRentalPrice() != null &&
                queryParams.getMaxRentalPrice() != null &&
                queryParams.getMinRentalPrice().compareTo(queryParams.getMaxRentalPrice()) > 0) {
            LogUtil.error("COSTUME", "VALIDATE_BUSINESS", "最低价格不能大于最高价格: min={}, max={}",
                    queryParams.getMinRentalPrice(), queryParams.getMaxRentalPrice());
            throw CostumeException.of(CostumeErrorCode.MIN_PRICE_GREATER_THAN_MAX, "最低价格不能大于最高价格");
        }
    }

    /**
     * 基础验证
     * @param queryParams
     */
    private void basicsValidateParams(CostumeQueryDTO queryParams) {
        // 页码验证
        if (queryParams.getPageNum() == null || queryParams.getPageNum() < 1) {
            queryParams.setPageNum(1);
            LogUtil.info("COSTUME", "VALIDATE_BASIC", "页码设置为默认值: 1");
        }

        // 页大小验证
        if (queryParams.getPageSize() == null || queryParams.getPageSize() < 1) {
            queryParams.setPageSize(20);
            LogUtil.info("COSTUME", "VALIDATE_BASIC", "页大小设置为默认值: 20");
        } else if (queryParams.getPageSize() > 100) {
            queryParams.setPageSize(100);
            LogUtil.info("COSTUME", "VALIDATE_BASIC", "页大小超过最大值，设置为: 100");
        }

        // 价格验证
        if (queryParams.getMinRentalPrice() != null && queryParams.getMinRentalPrice().compareTo(BigDecimal.ZERO) < 0) {
            LogUtil.error("COSTUME", "VALIDATE_BASIC", "最低价格不能小于0: {}", queryParams.getMinRentalPrice());
            throw CostumeException.of(CostumeErrorCode.INVALID_PRICE_RANGE, "商品价格不能小于0");
        }

        if (queryParams.getMaxRentalPrice() != null && queryParams.getMaxRentalPrice().compareTo(BigDecimal.ZERO) < 0) {
            LogUtil.error("COSTUME", "VALIDATE_BASIC", "最高价格不能小于0: {}", queryParams.getMaxRentalPrice());
            throw CostumeException.of(CostumeErrorCode.INVALID_PRICE_RANGE, "商品价格不能小于0");
        }

        // 排序字段验证
        if (queryParams.getSortBy() == null ||
                !Set.of("price", "sales", "createTime").contains(queryParams.getSortBy())) {
            queryParams.setSortBy("createTime");
            LogUtil.info("COSTUME", "VALIDATE_BASIC", "排序字段设置为默认值: createTime");
        }

        // 排序方向验证
        if (queryParams.getSortOrder() == null ||
                !Set.of("asc", "desc").contains(queryParams.getSortOrder())) {
            queryParams.setSortOrder("desc"); // 默认降序
            LogUtil.info("COSTUME", "VALIDATE_BASIC", "排序方向设置为默认值: desc");
        }
    }

    /**
     * 获取当前用户ID
     */
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            LogUtil.error("COSTUME", "GET_USER_ID", "用户认证信息为空");
            throw AuthException.of(AuthErrorCode.TOKEN_MISSING);
        }

        Object principal = authentication.getPrincipal();
        Long userId = null;

        if (principal instanceof LoginUser loginUser) {
            userId = loginUser.getUserId();
        }

        if (userId == null || userId <= 0) {
            LogUtil.error("COSTUME", "GET_USER_ID", "用户ID无效: {}", userId);
            throw AuthException.of(AuthErrorCode.USER_ID_INVALID);
        }

        LogUtil.info("COSTUME", "GET_USER_ID", "获取当前用户ID成功: {}", userId);
        return userId;
    }

    /**
     * 多级查询 - 修正为更适合分页查询的逻辑
     */
    private void checkCostumeListCache(CostumeQueryDTO queryParams, Long currentUserId) {
        String cacheKey = buildCostumeListCacheKey(queryParams, currentUserId);
        Object cached = redisUtil.get(cacheKey);
        if (cached != null) {
            LogUtil.info("COSTUME", "CHECK_CACHE", "从缓存获取服装列表数据");
        } else {
            LogUtil.info("COSTUME", "CHECK_CACHE", "缓存未命中，从数据库查询服装列表");
        }
    }

    /**
     * 构建服装列表缓存key
     */
    private String buildCostumeListCacheKey(CostumeQueryDTO queryParams, Long currentUserId) {
        return "costume:list:" + currentUserId + ":" + queryParams.getPageNum() + ":" +
                queryParams.getPageSize() + ":" + StrUtil.nullToEmpty(queryParams.getKeyword()) +
                ":" + StrUtil.nullToEmpty(queryParams.getSortBy());
    }
}